# Distributed under MIT License - See LICENSE
require 'net/https'
require 'uri'
require 'rexml/document'
require 'family_tree_api/exceptions'
require 'family_tree_api/url_encoder'

module FamilyTreeApi
  NamespacePrefix = ""
  class HttpCommunicator
    attr_accessor :session
  
    def initialize(options)
      @base_url = options[:base_url] || "http://www.dev.usys.org"
      @agent_string = options[:agent_string]
      if options[:session]
        @session = options[:session]
      elsif options[:username] && options[:password] && options[:api_key]
        @session = authenticate(options[:username], options[:password], options[:api_key])
        raise "Invalid username or password" unless @session 
      else
        raise "Please provide a username and password."
      end
    end
  
    def authenticate(username,password,api_key)
      url = "#{@base_url}/identity/v1/login?key=#{api_key}"
      uri = URI.parse(url)
      http = Net::HTTP.new(uri.host, uri.port)
      http.use_ssl = true if uri.scheme == 'https'
    
      req = Net::HTTP::Get.new(uri.path + '?' + uri.query)
      res = http.start do |ht|
        req.basic_auth username, password
        req['User-Agent'] = @agent_string
        ht.request(req)
      end
      result = parse_authentication(res.body)
      if result
        result
      end
    end
  
    def get(url)
      uri = URI.parse(@base_url+url)
      http = Net::HTTP.new(uri.host, uri.port)
      http.use_ssl = true if uri.scheme == 'https'
      full_url = get_full_url(uri)
      req = Net::HTTP::Get.new(full_url)
      res = http.start do |ht|
        req['Cookie'] = "USYSSESSIONID=#{@session}; JSESSIONID=#{@session}"
        req['User-Agent'] = @agent_string
        ht.request(req)
      end
      check_response_code(res)
      res
    end
  
    def post(url, xml)
      uri = URI.parse(@base_url+url)
      http = Net::HTTP.new(uri.host, uri.port)
      http.use_ssl = true if uri.scheme == 'https'
      full_url = get_full_url(uri)
      req = Net::HTTP::Post.new(full_url)
      req.body = xml
      res = http.start do |ht|
        req['Cookie'] = "USYSSESSIONID=#{@session}; JSESSIONID=#{@session}"
        req['User-Agent'] = @agent_string
        req['Content-Type'] = "text/xml"
        ht.request(req)
      end
      check_response_code(res)
      res
    end
  
    private
    
    def check_response_code(res)
      # puts res.code
      case res.code
      when '400'
        raise "Insufficient Parameters"
      when '401'
        raise "Unauthorized"
      when '403'
        raise "Forbidden"
      when '500'
        raise "Server Error"
      when '503'
        raise "Service Unavailable"
      end
    end

    def get_full_url(uri)
      if uri.query.nil?
        uri.path + "?sessionId=#{@session}"
      else
        uri.path + '?' + uri.query + "&sessionId=#{@session}"
      end
    end
    
    def parse_authentication(auth_xml)
      doc = REXML::Document.new auth_xml
      doc.elements["identity/session"].attributes["id"] unless doc.elements["identity/errors"]
    end
  
  end

  
end